#include "raftServerRpcUtil.h"

// 核心功能说明：
// kvserver的RPC与Raft节点之间的RPC不同：
// 此处的RPC是给客户端（clerk）调用KV服务器用的，因此只需要实现"调用者（caller）"功能，不需要实现"被调用者（callee）"逻辑
// 注意：实际使用时应先启动KV服务器，再尝试让客户端连接，中间建议加一点延迟，等待服务器端RPC服务启动完成

raftServerRpcUtil::raftServerRpcUtil(std::string ip, short port) {
    // 初始化RPC存根（stub）：
    // 1. 创建自定义的RPC通道（MprpcChannel），负责底层网络通信（连接指定ip:port，false表示不使用SSL等加密）
    // 2. 基于通道创建KV服务器的RPC存根（kvServerRpc_Stub），通过存根可以调用服务器端的RPC方法
    stub = new raftKVRpcProctoc::kvServerRpc_Stub(new rpc::MprpcChannel(ip, port, false));
}

raftServerRpcUtil::~raftServerRpcUtil() { delete stub; }

bool raftServerRpcUtil::Get(raftKVRpcProctoc::GetArgs *GetArgs, raftKVRpcProctoc::GetReply *reply) {
    rpc::MprpcController controller;
    // 调用存根的Get方法：通过RPC通道向服务器发送Get请求
    // 参数依次为：控制器、输入参数、输出参数、回调函数（此处为nullptr，表示同步调用）
    stub->Get(&controller, GetArgs, reply, nullptr);
    return !controller.Failed();
}

bool raftServerRpcUtil::PutAppend(raftKVRpcProctoc::PutAppendArgs *args, raftKVRpcProctoc::PutAppendReply *reply) {
    rpc::MprpcController controller;
    stub->PutAppend(&controller, args, reply, nullptr);
    if (controller.Failed()) {
        std::cout << controller.ErrorText() << std::endl;
    }
    return !controller.Failed();
}